/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.gtugs.repository;

import com.google.appengine.api.datastore.Cursor;

import org.datanucleus.store.appengine.query.JDOCursorHelper;
import org.gtugs.domain.Event;
import org.springframework.orm.jdo.support.JdoDaoSupport;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

/**
 * @author jasonacooper@google.com (Jason Cooper)
 */
public class JdoEventDao extends JdoDaoSupport implements EventDao {

  public JdoEventDao() {
    super();
    setPersistenceManagerFactory(PMF.get());
  }

  public Event getEvent(Long id) {
    PersistenceManager pm = getPersistenceManager();
    Event event = null;

    try {
      event = pm.getObjectById(Event.class, id);

      // Detach event
      event = pm.detachCopy(event);
    } catch (JDOObjectNotFoundException e) {
      return null;
    } finally {
      pm.close();
    }

    return event;
  }

  public List<Event> getEvents(boolean futureOnly) {
    PersistenceManager pm = getPersistenceManager();
    Query query = pm.newQuery(Event.class);

    query.setOrdering("startDate asc");

    if (futureOnly) {
      query.setFilter("startDate > startDateParam");
      query.declareParameters("java.util.Date startDateParam");
    }

    try {
      List<Event> results = null;
      if (futureOnly) {
        results = (List<Event>) query.execute(new Date());
      } else {
        results = (List<Event>) query.execute();
      }

      if (results != null && results.size() > 0) {
        return (List<Event>) pm.detachCopyAll(results);
      }
    } finally {
      query.closeAll();
      pm.close();
    }

    return null;
  }

  public List<Event> getEvents(Date startRange, Date endRange) {
    PersistenceManager pm = getPersistenceManager();
    Query query = pm.newQuery(Event.class);

    query.setFilter("startDate >= startRangeParam && startDate <= endRangeParam");
    query.declareParameters("java.util.Date startRangeParam, java.util.Date endRangeParam");

    try {
      List<Event> results = null;
      results = (List<Event>) query.execute(startRange, endRange);

      if (results != null && results.size() > 0) {
        return (List<Event>) pm.detachCopyAll(results);
      }
    } finally {
      query.closeAll();
      pm.close();
    }

    return null;
  }

  public List<Event> getEvents(Cursor cursor) {
    PersistenceManager pm = getPersistenceManager();
    Query query = pm.newQuery(Event.class);

    query.setRange(0, 20);

    if (cursor != null) {
      Map<String, Object> extensionMap = new HashMap<String, Object>();
      extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
      query.setExtensions(extensionMap);
    }

    try {
      List<Event> results = null;
      results = (List<Event>) query.execute();

      if (results != null && results.size() > 0) {
        return (List<Event>) pm.detachCopyAll(results);
      }
    } finally {
      query.closeAll();
      pm.close();
    }

    return null;
  }

  public List<Event> getEventsForChapter(Long chapterId, boolean futureOnly) {
    PersistenceManager pm = getPersistenceManager();
    Query query = pm.newQuery(Event.class);

    if (futureOnly) {
      query.setFilter("chapterId == chapterIdParam && startDate > startDateParam");
      query.declareParameters("Long chapterIdParam, java.util.Date startDateParam");
    } else {
      query.setFilter("chapterId == chapterIdParam");
      query.declareParameters("Long chapterIdParam");
    }
    query.setOrdering("startDate asc");

    try {
      List<Event> results = null;
      if (futureOnly) {
        results = (List<Event>) query.execute(chapterId, new Date());
      } else {
        results = (List<Event>) query.execute(chapterId);
      }

      if (results != null && results.size() > 0) {
        return (List<Event>) pm.detachCopyAll(results);
      }
    } finally {
      query.closeAll();
      pm.close();
    }

    return null;
  }

  public List<Event> getPastEvents(Long chapterId) {
    PersistenceManager pm = getPersistenceManager();
    Query query = pm.newQuery(Event.class);

    query.setFilter("chapterId == chapterIdParam && startDate < startDateParam");
    query.declareParameters("Long chapterIdParam, java.util.Date startDateParam");
    query.setOrdering("startDate desc");

    try {
      List<Event> results = (List<Event>) query.execute(chapterId, new Date());

      if (results != null && results.size() > 0) {
        return (List<Event>) pm.detachCopyAll(results);
      }
    } finally {
      query.closeAll();
      pm.close();
    }

    return null;
  }

  public void storeEvent(Event event) {
    getJdoTemplate().makePersistent(event);
  }
}
